package com.after.saas.common.utils;

import cn.hutool.core.codec.Base64Decoder;
import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description
 * @Classname SignatureUtil
 * @Author hjchen
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2022/8/11 10:44
 */
public class SignatureUtil {

    private final static String PRIVATE_KEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDmx9wncr8tBrIQmm8k0hsYNDzqTRFAOVNkHznyvnsC45ZaWIWlJ7gj+CeBw5BKJ8eDvfq9jFeGFUMmwtI5+489j2o42+uI5VbjMg8eAwyus4KzA+Fl60aO3wFVG2iQhcGxxrzCSmdjDT25PuhULXR1sPisil46Uzq3s8GO0B96cHrC8TKjcPHDLVEL6Ho+pD8Zm4TxHx+RI5/q8jVZsc+/XcqnpQw3Om2YaQtZdFgWg1/QACQSNHeCMvkzLouWlZftXXx/biuijkbmg4eHlL6rITfYMQIcDQZGyD9oXM6AXPA1/zx5YYzpW9I5l5b3UuWaXLSzwpt3utZ7Lg4S7JdhAgMBAAECggEADj51syWc8R2Brg6qH36sV3EZ9WguUWV4ZSycOgRRuVrss8TU8t2huu6dGaBFbp5H7TSznjFkUY1MaL8LlLKXI7iPWNUSE4/8LeewES0lAj9oKL5rkgvUfgr7nRIlAQ6QZvWaPu+ys+VkUuO0GUX48y6qGpQrvrPWYvJAVx03ZCohFLdzTZGUt4M2/ac29TylV5S4SRjmBgludmQv5JHl6Vg9gp0/L7Qb/NI0kuo6KsT0M0Fh67MyNVXvx6QCoXIRGNlb6kPj5Vcj4v2rFmdWGsa/pDh8/Al4GpqLuoEt0d2djhqnZcPSHZlV7wd0WX0o/Ifay/fHORHtX1cOd0BZhQKBgQD6uKEa6vUtMYTDZ/yxJfP0w12Pb7UC5twQrLgzSCDWvMIThCknEkCodsNQqhb3DbFyI7gpmQ5QA6dXkXvsd3XLnKFTHxWhM5lL4ttlcN5pRlRk5lgVyvDeFf/O/jFbyRXe50gQFeGmtBKFhUYczxlWpMCqUFBG9FTn54LH7u3uSwKBgQDro8CuSBdf/5gRCNo3UMlxPqG1mKEqNn84rSEeLxJdv9RuPXKKhObNnc5l/3/+DV5+NaR+jNL/59j2RkKFdgmtHqUz+B9x3PMBFOY2t091WNkTT4Fh/9HI38vmIJJVeVq5OnM7ze+sZk5UNmnyF2vXojS72/lPtoZ/TLIvRi6VgwKBgHdgGTUb0gjmnvP7OxGNpI5RxuZYpbLwAK/fzQR9v0T/MtjgAEgeJLMReQWbNrwCxQ43e6Qyv+HRG4hSONLqPifoN9e/4SiTzNWY+iVejEdLuTshgac+rVjQ2K/Rz+aH4+Xx8RnXkU0yR+9S+YMWCFZ8s09kVhSymQqh7F8NoDPpAoGAbmlIO2FkMoMcyb6QISMlgH6MXv6pZZIrgm78+Zusy2i7LPx10xn625V5xKk3W97/y7tu3C04INiN/LdnLAnm9stJNVSpxzx0UKluRW0XOjDrZfT29uhbb/gNHkNczdgS/n+4xujzyKAXS7ZDZkA7M8q5Utz7sLIhyzwwsZ387ekCgYEAn8KD9UM6ItlnylDZCLPTOT345cYV0VN/q8CF34eYr1z7j/rlTRmIS3081gixVqVRBs7soFfGq1xSKboJzEsjPRPWDAYrBM9EA+Ldu/57IjZYKdBL+tDMVpvsDcLvg+5o7G2D5Ln4GpZMJQXRYjJnEwZeS8taJb2SLuEvSPkhzQo=";
    private final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5sfcJ3K/LQayEJpvJNIbGDQ86k0RQDlTZB858r57AuOWWliFpSe4I/gngcOQSifHg736vYxXhhVDJsLSOfuPPY9qONvriOVW4zIPHgMMrrOCswPhZetGjt8BVRtokIXBsca8wkpnYw09uT7oVC10dbD4rIpeOlM6t7PBjtAfenB6wvEyo3Dxwy1RC+h6PqQ/GZuE8R8fkSOf6vI1WbHPv13Kp6UMNzptmGkLWXRYFoNf0AAkEjR3gjL5My6LlpWX7V18f24roo5G5oOHh5S+qyE32DECHA0GRsg/aFzOgFzwNf88eWGM6VvSOZeW91Llmly0s8Kbd7rWey4OEuyXYQIDAQAB";

    /**
     * 执行签名
     *
     * @param rsaPrivateKey 私钥
     * @param src           参数内容
     * @return 签名后的内容，base64后的字符串
     */
    public static String executeSignature(String rsaPrivateKey, String src) {
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA1withRSA, rsaPrivateKey, null);
        return Base64Encoder.encode(sign.sign(src.getBytes(StandardCharsets.UTF_8)));
    }

    /**
     * 验证签名
     *
     * @param rsaPublicKey 公钥
     * @param signStr      签名
     * @param src          参数内容
     * @return 验证结果
     */
    public static boolean verifySignature(String rsaPublicKey, String signStr, String src) {
        Sign sign = SecureUtil.sign(SignAlgorithm.SHA1withRSA, null, rsaPublicKey);
        return sign.verify(src.getBytes(StandardCharsets.UTF_8), Base64Decoder.decode(signStr));
    }

    /**
     * 验证签名
     *
     * @param entPublicKey 公钥
     * @param signStr      签名
     * @param params       待签名参数
     * @return 验证结果
     */
    public static boolean verifySignatureByMap(String entPublicKey, String signStr, Map<String, Object> params) {
        return verifySignature(entPublicKey, signStr, sortParams(params));
    }

    /**
     * @return java.lang.String
     * @Author hjchen
     * @Description 将需要签名的参数内容按参数名的字典顺序进行排序，并拼接为字符串
     * @Date 2022/8/11 18:18
     * @Param [param]
     **/
    public static String sortParams(Map<String, Object> param) {
        StringBuilder sb = new StringBuilder();
        param.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&"));
        return sb.substring(0, sb.length() - 1);
    }

    public static void main(String[] args) {
        Map<String, Object> param = new HashMap<>(16);
        // 请求所需的参数
        param.put("userName", "×××");
        param.put("phone", "12580");
        param.put("address", "北京");
        param.put("status", 1);
        String sign = executeSignature(PRIVATE_KEY, sortParams(param));
        System.out.println(sign);
        System.out.println(verifySignature(PUBLIC_KEY, sign, sortParams(param)));
        System.out.println(sortParams(param));
        param.put("sign", sign);
        String signStr = (String) param.remove("sign");
        System.out.println(verifySignatureByMap(PUBLIC_KEY, signStr, param));
    }
}
